#include "serializer/io.h"
#include "serializer/serializer.h"
#include "serializer/traits.h"

#include <gtest/gtest.h>

#include <cstddef>
#include <string>
#include <vector>

using namespace serializer;

/**
 * 测试基础类型概念
 */
TEST(ConceptsTest, arithmetic_type_concept)
{
    // 基础算术类型应该满足概念
    static_assert(arithmetic_type<int>);
    static_assert(arithmetic_type<unsigned int>);
    static_assert(arithmetic_type<long>);
    static_assert(arithmetic_type<unsigned long>);
    static_assert(arithmetic_type<long long>);
    static_assert(arithmetic_type<unsigned long long>);
    static_assert(arithmetic_type<short>);
    static_assert(arithmetic_type<unsigned short>);
    static_assert(arithmetic_type<char>);
    static_assert(arithmetic_type<signed char>);
    static_assert(arithmetic_type<unsigned char>);
    static_assert(arithmetic_type<bool>);

    // 浮点类型应该满足概念
    static_assert(arithmetic_type<float>);
    static_assert(arithmetic_type<double>);
    static_assert(arithmetic_type<long double>);

    // 非算术类型不应该满足概念
    static_assert(!arithmetic_type<std::string>);
    static_assert(!arithmetic_type<std::vector<int>>);
    static_assert(!arithmetic_type<void *>);
    static_assert(!arithmetic_type<int *>);
}

/**
 * 测试 IEEE754 浮点类型概念
 */
TEST(ConceptsTest, ieee754_float_concept)
{
    // 标准浮点类型应该满足概念
    static_assert(ieee754_float<float>);
    static_assert(ieee754_float<double>);

    // 长双精度浮点数可能不满足（取决于实现）
    // static_assert(ieee754_float<long double>); // 平台相关

    // 非浮点类型不应该满足概念
    static_assert(!ieee754_float<int>);
    static_assert(!ieee754_float<bool>);
    static_assert(!ieee754_float<std::string>);
}

/**
 * 测试可移植算术类型概念
 */
TEST(ConceptsTest, portable_arithmetic_type_concept)
{
    // 可移植的算术类型应该满足概念
    static_assert(portable_arithmetic_type<int>);
    static_assert(portable_arithmetic_type<unsigned int>);
    static_assert(portable_arithmetic_type<float>);
    static_assert(portable_arithmetic_type<double>);
    static_assert(portable_arithmetic_type<bool>);
    static_assert(portable_arithmetic_type<char>);

    // 长双精度浮点数可能不可移植
    // static_assert(!portable_arithmetic_type<long double>); // 平台相关

    // 非算术类型不应该满足概念
    static_assert(!portable_arithmetic_type<std::string>);
    static_assert(!portable_arithmetic_type<void *>);
}

/**
 * 测试字节类型概念
 */
TEST(ConceptsTest, byte_type_concept)
{
    // 字节类型应该满足概念
    static_assert(byte_type<std::byte>);
    static_assert(byte_type<unsigned char>);
    static_assert(byte_type<char>);
    static_assert(byte_type<signed char>);

    // 非字节类型不应该满足概念
    static_assert(!byte_type<int>);
    static_assert(!byte_type<short>);
    static_assert(!byte_type<float>);
    static_assert(!byte_type<std::string>);
}

/**
 * 用于测试写入器概念的模拟类型
 */
class MockWriter
{
public:
    void write_bytes(const std::byte * data, std::size_t size) {}
    std::size_t position() const noexcept { return 0; }
    std::size_t bytes_written() const noexcept { return 0; }
    bool can_write(std::size_t size) const noexcept { return true; }
};

class MockExtendedWriter : public MockWriter
{
public:
    using MockWriter::write_bytes; // 继承基类的write_bytes方法
    void write_bytes(kp::span<const std::byte> data) {}
    void write_string_view(std::string_view str) {}
};

class MockSeekableWriter : public MockExtendedWriter
{
public:
    void seek(std::size_t pos) {}
    std::size_t capacity() const noexcept { return 1000000; }
};

/**
 * 测试写入器概念
 */
TEST(ConceptsTest, writer_concepts)
{
    // 基础写入器概念
    static_assert(basic_writer<MockWriter>);
    static_assert(basic_writer<MockExtendedWriter>);
    static_assert(basic_writer<vector_writer>);

    // 扩展写入器概念
    static_assert(extended_writer<MockExtendedWriter>);
    static_assert(extended_writer<vector_writer>);
    static_assert(!extended_writer<MockWriter>);

    // 可寻址写入器概念
    static_assert(seekable_writer<MockSeekableWriter>);
    static_assert(!seekable_writer<MockWriter>);
    static_assert(!seekable_writer<MockExtendedWriter>);

    // 统一写入器概念
    static_assert(writer<MockWriter>);
    static_assert(writer<MockExtendedWriter>);
    static_assert(writer<MockSeekableWriter>);
    static_assert(writer<vector_writer>);

    // 非写入器类型不应该满足概念
    static_assert(!writer<int>);
    static_assert(!writer<std::string>);
}

/**
 * 用于测试读取器概念的模拟类型
 */
class MockReader
{
public:
    void read_bytes(std::byte * data, std::size_t size) {}
    std::size_t position() const noexcept { return 0; }
    bool has_data() const noexcept { return true; }
};

class MockExtendedReader : public MockReader
{
public:
    void read_bytes(std::byte * data, std::size_t size) {}
    void read_bytes(kp::span<std::byte> data) {}
    std::string read_string(std::size_t size) { return ""; }
    std::size_t remaining_bytes() const noexcept { return 1000; }
    bool can_read(std::size_t size) const noexcept { return true; }
};

class MockSeekableReader : public MockExtendedReader
{
public:
    void seek(std::size_t pos) {}
    std::size_t size() const noexcept { return 1000000; }
};

/**
 * 测试读取器概念
 */
TEST(ConceptsTest, reader_concepts)
{
    // 基础读取器概念
    static_assert(basic_reader<MockReader>);
    static_assert(basic_reader<MockExtendedReader>);
    static_assert(basic_reader<vector_reader>);

    // 扩展读取器概念
    static_assert(extended_reader<MockExtendedReader>);
    static_assert(extended_reader<vector_reader>);
    static_assert(!extended_reader<MockReader>);

    // 可寻址读取器概念
    static_assert(seekable_reader<MockSeekableReader>);
    static_assert(seekable_reader<vector_reader>);
    static_assert(!seekable_reader<MockReader>);
    static_assert(!seekable_reader<MockExtendedReader>);

    // 统一读取器概念
    static_assert(reader<MockReader>);
    static_assert(reader<MockExtendedReader>);
    static_assert(reader<MockSeekableReader>);
    static_assert(reader<vector_reader>);

    // 非读取器类型不应该满足概念
    static_assert(!reader<int>);
    static_assert(!reader<std::string>);
}

/**
 * 用于测试序列化选项概念的模拟类型
 */
struct MockOptions
{
    // 基础选项接口
    byte_order get_byte_order() const { return byte_order::native; }
    std::size_t max_container_size() const { return 1000000; }
    std::size_t max_string_length() const { return 1000000; }
    std::size_t max_recursion_depth() const { return 100; }

    MockOptions with_byte_order(byte_order order) const { return *this; }
    auto with_max_container_size(std::size_t size) const { return *this; }
    auto with_max_string_length(std::size_t length) const { return *this; }
    auto with_max_recursion_depth(std::size_t depth) const { return *this; }
};

struct MockExtendedOptions : public MockOptions
{
    // 扩展选项接口
    bool enable_compression() const { return false; }
    bool enable_checksum() const { return false; }
    std::uint32_t version() const { return 1; }
    bool enable_debug() const { return false; }
};

/**
 * 测试序列化选项概念
 */
TEST(ConceptsTest, serialization_options_concepts)
{
    // 基础选项概念
    static_assert(serialization_options<MockOptions>);
    static_assert(serialization_options<MockExtendedOptions>);
    static_assert(serialization_options<default_options>);

    // 扩展选项概念
    static_assert(extended_serialization_options<MockExtendedOptions>);
    static_assert(!extended_serialization_options<default_options>);
    static_assert(!extended_serialization_options<MockOptions>);

    // 非选项类型不应该满足概念
    static_assert(!serialization_options<int>);
    static_assert(!serialization_options<std::string>);
}

/**
 * 用于测试序列化上下文概念的模拟类型
 */
struct MockContext
{
    std::size_t current_depth() const noexcept { return 0; }
    void increment_depth() {}
    void decrement_depth() noexcept {}
    bool check_depth_limit() const noexcept { return true; }
};

struct MockExtendedContext : public MockContext
{
    bool has_circular_reference(const void * ptr) const noexcept { return false; }
    void add_reference(const void * ptr) {}
    void remove_reference(const void * ptr) {}
    std::size_t bytes_processed() const noexcept { return 0; }
    std::size_t objects_processed() const noexcept { return 0; }
};

/**
 * 测试序列化上下文概念
 */
TEST(ConceptsTest, serialization_context_concepts)
{
    // 基础上下文概念
    static_assert(serialization_context<MockContext>);
    static_assert(serialization_context<MockExtendedContext>);

    // 扩展上下文概念
    static_assert(extended_serialization_context<MockExtendedContext>);
    static_assert(!extended_serialization_context<MockContext>);

    // 非上下文类型不应该满足概念
    static_assert(!serialization_context<int>);
    static_assert(!serialization_context<std::string>);
}

/**
 * 用于测试序列化错误概念的模拟类型
 */
struct MockError
{
    std::string message() const { return ""; }
    int code() const noexcept { return 0; }
    std::size_t position() const noexcept { return 0; }
};

struct MockExtendedError : public MockError
{
    std::string type_name() const { return ""; }
    std::string stack_trace() const { return ""; }
    std::string context() const { return ""; }
};

/**
 * 测试序列化错误概念
 */
TEST(ConceptsTest, serialization_error_concepts)
{
    // 基础错误概念
    static_assert(serialization_error<MockError>);
    static_assert(serialization_error<MockExtendedError>);

    // 扩展错误概念
    static_assert(extended_serialization_error<MockExtendedError>);
    static_assert(!extended_serialization_error<MockError>);

    // 非错误类型不应该满足概念
    static_assert(!serialization_error<int>);
    static_assert(!serialization_error<std::string>);
}

/**
 * 测试概念的组合使用
 */
TEST(ConceptsTest, concept_combinations)
{
    // 测试类型同时满足多个概念
    static_assert(arithmetic_type<int> && portable_arithmetic_type<int>);
    static_assert(ieee754_float<float> && portable_arithmetic_type<float>);
    static_assert(byte_type<std::byte> && !arithmetic_type<std::byte>);

    // 测试 I/O 类型的概念组合
    static_assert(writer<vector_writer> && extended_writer<vector_writer>);
    static_assert(reader<vector_reader> && extended_reader<vector_reader> &&
                  seekable_reader<vector_reader>);

    // 测试选项和上下文的概念组合
    static_assert(serialization_options<default_options>);
    static_assert(extended_serialization_options<MockExtendedOptions>);
}

/**
 * 测试概念的负面情况
 */
TEST(ConceptsTest, negative_concept_tests)
{
    // 确保不相关的类型不满足概念
    struct UnrelatedType
    {
    };

    static_assert(!arithmetic_type<UnrelatedType>);
    static_assert(!ieee754_float<UnrelatedType>);
    static_assert(!portable_arithmetic_type<UnrelatedType>);
    static_assert(!byte_type<UnrelatedType>);
    static_assert(!writer<UnrelatedType>);
    static_assert(!reader<UnrelatedType>);
    static_assert(!serialization_options<UnrelatedType>);
    static_assert(!serialization_context<UnrelatedType>);
    static_assert(!serialization_error<UnrelatedType>);

    // 测试不完整的实现
    struct IncompleteWriter
    {
        void write_bytes(const std::byte * data, std::size_t size) {}
        // 缺少其他必需的方法
    };

    static_assert(!writer<IncompleteWriter>);
}

/**
 * 运行时概念验证测试
 */
TEST(ConceptsTest, runtime_concept_verification)
{
    // 验证实际类型在运行时的行为符合概念要求
    vector_writer w;
    vector_reader r(w.data());
    default_options opts;

    // 这些调用应该成功编译和执行
    EXPECT_TRUE(w.can_write(100));
    EXPECT_EQ(w.position(), 0);
    EXPECT_EQ(w.bytes_written(), 0);

    EXPECT_EQ(r.position(), 0);
    EXPECT_EQ(r.remaining_bytes(), 0);
    EXPECT_FALSE(r.has_data());

    // 测试选项的链式调用
    auto modified_opts =
        opts.with_max_container_size(1000).with_max_string_length(500).with_max_recursion_depth(10);

    // 这些调用应该成功
    EXPECT_NO_THROW(modified_opts.with_varint_lengths(true));
    EXPECT_NO_THROW(modified_opts.with_byte_order(byte_order::big_endian));
}